package com.xiangyueEducation.uploaderCloud.service.impl;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiangyueEducation.uploaderCloud.utils.Result;
import com.xiangyueEducation.uploaderCloud.constant.RedisConstant;
import com.xiangyueEducation.uploaderCloud.mapper.ModuleMapper;
import com.xiangyueEducation.uploaderCloud.mapper.QuestionsMapper;
import com.xiangyueEducation.uploaderCloud.pojo.dto.PageQuery;
import com.xiangyueEducation.uploaderCloud.pojo.entity.Modules;
import com.xiangyueEducation.uploaderCloud.pojo.entity.Questions;
import com.xiangyueEducation.uploaderCloud.pojo.vo.PageVo;
import com.xiangyueEducation.uploaderCloud.service.ModuleService;
import org.springframework.data.redis.core.ZSetOperations.TypedTuple;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Service
public class ModuleServiceImpl  extends ServiceImpl<ModuleMapper, Modules> implements ModuleService {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private ModuleMapper moduleMapper;
    @Autowired
    private QuestionsMapper questionsMapper;
    @Override
    public Result insert(Modules moduleDTO, Long userId) {
        // 将用户id存入
        moduleDTO.setUserId(userId);
        moduleDTO.setCreateTime(LocalDateTime.now());
        moduleDTO.setUpdateTime(LocalDateTime.now());
        moduleMapper.insert(moduleDTO);
        //存入数据库之后
        Long id = moduleDTO.getId();

        //存入缓存
        stringRedisTemplate.opsForZSet().add(RedisConstant.MODULE_CACHE_KEY,JSONUtil.toJsonStr(moduleDTO), (double) moduleDTO.getCreateTime().toInstant(ZoneOffset.of("+8")).toEpochMilli());
        return Result.ok(id);
    }

    @Override
    public Modules queryExistById(Long testId) {
        Modules modules = moduleMapper.selectById(testId);
        return modules;
    }


    @Override
    public PageVo queryModules(PageQuery pageQuery) {
        Integer pageSize = pageQuery.getPageSize();
        Integer pageNo = pageQuery.getPageNo();
        String key = RedisConstant.MODULE_CACHE_KEY;
        long start = (long) (pageNo - 1) * pageSize;
        long end = start + pageSize - 1;
        Set<String> range = stringRedisTemplate.opsForZSet().range(key, start, end);
        //如果s存在，则直接返回
        if(range!=null&&range.size()>0){
            //将每一个json对象都转成真实的对象
            List<Modules> list = range.stream().map(moduleJson->JSONUtil.toBean(moduleJson,Modules.class)).toList();
            Long total = stringRedisTemplate.opsForZSet().zCard(key);
            return new PageVo(total,list);
        }
        //如果s不存在，则直接去数据库中查
        //添加分页基本参数
        Page<Modules> modulesPage = new Page<>(pageNo, pageSize);
        //设置排序参数，按照时间顺序，升序
        OrderItem orderItem1 = new OrderItem().setAsc(true).setColumn("create_time");
        modulesPage.addOrder(orderItem1);
        //去数据库查
        Page<Modules> page = page(modulesPage);
        List<Modules> records = page.getRecords();
        long total = page.getTotal();
        PageVo pageVo = new PageVo(total,records);
        if (records.size()==0) return pageVo;
        //查完以后，存入缓存
        //批量插入
        Set<TypedTuple<String>> tuples = new HashSet<>();
        for (Modules record:records){
            TypedTuple<String> objectTypedTuple = new TypedTuple<>(){
                @Override
                public String getValue() {
                    return JSONUtil.toJsonStr(record);
                }

                @Override
                public Double getScore() {
                    return (double) record.getCreateTime().toInstant(ZoneOffset.of("+8")).toEpochMilli();
                }

                @Override
                public int compareTo(TypedTuple<String> o) {
                    return Double.compare(this.getScore(),o.getScore());
                }
            };
            tuples.add(objectTypedTuple);
        }
        stringRedisTemplate.opsForZSet().add(key,tuples);
        //设置过期时间为30天
        stringRedisTemplate.expire(key,RedisConstant.MODULE_TTL,TimeUnit.DAYS);
        return pageVo;
    }
    @Transactional
    @Override
    public void removeWithQuestion(Long moduleId) {
        removeById(moduleId);
        //构建删除模块，删除此处
        QueryWrapper<Questions> questionsQueryWrapper = new QueryWrapper<>();
        questionsQueryWrapper.eq("test_id",moduleId);
        questionsMapper.delete(questionsQueryWrapper);

    }
}
